from .models import Quizzes, Questionnaire, User  # 导入数据库模型
from django_redis import get_redis_connection  # 导入redis
from django.http import JsonResponse as JR  # 导入JsonResponselei
from django.views.generic.base import View
from cms.models import Doctor, PlatformLog  # 导入数据库模型
from django.core.mail import send_mail  # 导入邮件模块
from django.shortcuts import render
from UPI import settings
import random
import json
import time


# 重写JsonResponse对象，默认返回中文和内容可为列表
class JsonResponse(JR):
    def __init__(self, data, safe=False, json_dumps_params={'ensure_ascii': False}, **kwargs):
        super(JsonResponse, self).__init__(data, safe=safe, json_dumps_params=json_dumps_params)


# 时间戳工具
def formatTime(timestamp='', date=False):
    """
    :param timestamp: 时间戳
    :param date: 只返回日期
    :return: 日期字符串
    """
    if timestamp:
        return time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(timestamp))
    else:
        if date:
            return time.strftime("%Y-%m-%d")
        else:
            return time.strftime("%Y-%m-%d %H:%M:%S")


# 邮箱6位数字验证码
def get_auth_code():
    """
    :return: 6位数验证码
    """
    conn = get_redis_connection('auth_code')
    codes = [i.decode() for i in conn.keys()]  # 获取全部值
    print(codes)
    while True:
        code = random.randint(100000, 999999)
        if code not in codes:
            return code


# 校验邮箱
def judge_email(code, email):
    """
    传入参数与redis缓存中记录值比较
    :param code: 验证码
    :param email: 邮箱
    :return: bool
    """
    conn = get_redis_connection('auth_code')
    codes = [i.decode() for i in conn.keys()]  # 获取全部值
    if code in codes:
        e = conn.get(code).decode()
        if e == email:
            return True
        else:
            return False
    else:
        return False


# 登陆视图
class LoginView(View):
    """
    登录视图类，只接受get和post请求(下面的视图类都一样)
    """

    def get(self, res):
        """
        :param res: request请求对象
        :return: HTML
        """
        return render(res, 'front/login.html')

    def post(self, res):
        action = res.POST.get('action')  # 行为关键字
        if action == 'register':  # 注册
            name = res.POST.get('name')  # 用户名
            pwd = res.POST.get('pwd')  # 密码
            email = res.POST.get('email')  # 邮箱
            code = res.POST.get('code')  # 验证码
            if User.objects.filter(email=email):  # 判断邮箱是否已注册
                return JsonResponse({'state': False, 'msg': '此邮箱已注册！'}, json_dumps_params={'ensure_ascii': False},
                                    safe=False)
            if judge_email(code, email):  # 判断验证码是否正确
                data = {i.id: {'id': i.id, 'title': i.title, 'state': False, 'time': '', 'result': {}} for i in
                        Questionnaire.objects.all()}
                User.objects.create(name=name, email=email, pwd=pwd, data=data,
                                    last_login=formatTime(date=True))  # 创建用户，写入数据库
                # 记录平台数据：注册人数
                log = PlatformLog.objects.filter(date=formatTime(date=True))
                if log:
                    log = log.first()
                    log.log['register'] += 1
                    log.save()
                else:
                    PlatformLog.objects.create(date=formatTime(date=True),
                                               log={"register": 1, "visit": 1, "test": 0, "advisory": 0})
                return JsonResponse({'state': True})
            else:
                return JsonResponse({'state': False, 'msg': '验证码错误！'}, json_dumps_params={'ensure_ascii': False},
                                    safe=False)
        elif action == 'auth_code':  # 获取验证码
            email = res.POST.get('email')
            try:
                # 发送邮件
                auth_code = get_auth_code()
                send_mail(
                    # 发送邮件的标题
                    '大学生心理健康评估',
                    # 发送邮件的内容
                    f'欢迎注册！您的验证码：{auth_code}，5分钟内有效。',
                    # 发送者
                    '2870093961@qq.com',
                    # 接受者
                    [email],
                    # 发送失败是否返回错误信息
                    fail_silently=True,
                )
                # 写入redis缓存
                conn = get_redis_connection('auth_code')
                conn.setex(auth_code, 300, email)
                return JsonResponse({'state': True})
            except:
                return JsonResponse({'state': False})
        elif action == 'login':  # 登录
            email = res.POST.get('email')
            pwd = res.POST.get('pwd')
            user = User.objects.filter(email=email)
            if user:  # 判断用户是否存在
                user = user.first()
                if user.pwd == pwd:  # 判断密码是否正确
                    user.last_login = formatTime(date=True)  # 记录登录时间
                    user.save()
                    # 返回状态和uid
                    return JsonResponse({'state': True, 'uid': user.id}, json_dumps_params={'ensure_ascii': False},
                                        safe=False)
                else:
                    return JsonResponse({'state': False, 'msg': '密码错误！'}, json_dumps_params={'ensure_ascii': False},
                                        safe=False)
            else:
                return JsonResponse({'state': False, 'msg': '用户不存在！'}, json_dumps_params={'ensure_ascii': False},
                                    safe=False)
        elif action == 'forget':  # 忘记密码
            email = res.POST.get('email')
            user = User.objects.filter(email=email)
            if user:
                # 发送密码到用户邮箱
                try:
                    send_mail(
                        # 发送邮件的标题
                        '大学生心理健康评估',
                        # 发送邮件的内容
                        f'您的密码为：{user.first().pwd}，登陆后请尽快修改。',
                        # 发送者
                        '2870093961@qq.com',
                        # 接受者
                        [email],
                        # 发送失败是否返回错误信息
                        fail_silently=True,
                    )
                    return JsonResponse({'state': True})
                except:
                    return JsonResponse({'state': False})
            else:
                return JsonResponse({'state': False, 'msg': '没有此用户！'}, json_dumps_params={'ensure_ascii': False},
                                    safe=False)


# 问卷视图
class TestsView(View):
    def get(self, res):
        tid = res.GET.get('id')  # 问卷ID
        q = Questionnaire.objects.get(id=tid)  # 通过ID从数据库查询问卷数据
        context = {
            "tid": q.id,
            "title": q.title,
            "tips": q.tips,
            "apply": q.apply,
            "options": q.options,
            "resutl": q.result,
            "quizzes": []
        }
        for i in q.quizzes:  # 查询问卷中的所有题目
            data = {
                "title": i['title'],
                "quizzes": [],
            }
            for j in i['quizzes']:
                data['quizzes'].append({
                    'title': Quizzes.objects.get(id=j).quizzes,
                    'value': ''
                })
            context['quizzes'].append(data)
        # 返回问卷页面
        return render(res, 'front/tests.html', context=context)

    def post(self, res):
        tid = res.POST.get('tid')  # 问卷ID
        uid = res.COOKIES.get('uid')  # 用户ID
        radar = json.loads(res.POST.get('radar'))  # 雷达图数据
        bar = json.loads(res.POST.get('bar'))  # 柱状图数据
        user = User.objects.get(id=uid)  # 查询用户
        user.data[tid] = {'id': int(tid), 'title': Questionnaire.objects.get(id=tid).title, 'state': True,
                          'time': formatTime(), 'result': {
                'radar': radar,
                'bar': bar
            }}
        # 保存测试结果
        user.save()
        # 记录平台数据：测试次数
        log = PlatformLog.objects.filter(date=formatTime(date=True))
        if log:
            log = log.first()
            log.log['test'] += 1
            log.save()
        else:
            PlatformLog.objects.create(date=formatTime(date=True),
                                       log={"register": 0, "visit": 1, "test": 1, "advisory": 0})
        return JsonResponse({'state': True})


# 用户界面视图
class UserView(View):
    def get(self, res):
        uid = res.COOKIES.get('uid')  # 用户ID
        user = User.objects.get(id=uid)  # 通过ID，在数据库中查询用户数据
        context = {
            "quizzes": [],
            "head": user.head,
            "name": user.name,
            "email": user.email,
            "sex": user.sex,
            "age": user.age,
            "doctor": [],
            "advisory": user.advisory
        }
        for i in Questionnaire.objects.all():  # 遍历用户答题状态
            d = {
                'id': i.id,
                "title": i.title,
                "tips": i.tips,
                "apply": i.apply,
            }
            if str(i.id) in user.data:
                d["state"] = user.data[str(i.id)]['state']
                d["time"] = user.data[str(i.id)]['time']
                d["result"] = user.data[str(i.id)]['result']
            else:
                d["state"] = False
                d["time"] = ''
                user.data[i.id] = {'id': i.id, 'title': i.title, 'state': False, 'time': '', 'result': {}}
            context['quizzes'].append(d)
        context['quizzes'] = json.dumps(context['quizzes'], ensure_ascii=False)
        user.save()
        for i in Doctor.objects.all():  # 生成心理医生咨询列表
            context["doctor"].append({
                "id": i.id,
                "name": i.name,
                "picture": i.picture,
                "office": i.office,
                "level": i.level,
                "hospital": i.hospital,
                "serve": i.serve,
                "score": i.score,
                "intro": i.intro,
            })
        return render(res, 'front/index.html', context=context)

    def post(self, res):
        action = res.POST.get('action')  # 行为关键字
        uid = res.COOKIES.get('uid')  # 从cookies中提取用户ID
        if action == 'sex':  # 修改性别
            try:
                sex = res.POST.get('sex')
                User.objects.filter(id=uid).update(sex=True if sex == 'true' else False)
                return JsonResponse({'state': True})
            except:
                return JsonResponse({'state': False})
        elif action == 'age':  # 修改年纪
            try:
                age = int(res.POST.get('age'))
                User.objects.filter(id=uid).update(age=age)
                return JsonResponse({'state': True})
            except:
                return JsonResponse({'state': False})
        elif action == 'name':  # 修改名称
            try:
                name = res.POST.get('name')
                User.objects.filter(id=uid).update(name=name)
                return JsonResponse({'state': True, 'name': name})
            except:
                return JsonResponse({'state': False})
        elif action == 'pwd':  # 修改密码
            try:
                pwd = res.POST.get('pwd')
                User.objects.filter(id=uid).update(pwd=pwd)
                return JsonResponse({'state': True, 'name': pwd})
            except:
                return JsonResponse({'state': False})
        elif action == 'head':  # 修改头像
            try:
                file = res.FILES.get('file')  # 获取文件对象
                file_path = f'/static/images/{int(time.time() * 10)}.jpg'  # 存储路径
                with open(str(settings.BASE_DIR) + file_path, 'wb') as fp:  # 保存文件
                    fp.write(file.read())
                User.objects.filter(id=uid).update(head=file_path)  # 更新用户数据
                return JsonResponse({'state': True})
            except:
                return JsonResponse({'state': False})
        elif action == 'advisory':  # 心理咨询
            try:
                data = json.loads(res.POST.get('data'))  # 获取表单数据
                data['date'] = formatTime()
                doctor = Doctor.objects.get(id=data['doctor'])  # 医生信息
                doctor.task.append({
                    "id": uid,
                    "name": data['name'],
                    "tel": data['tel'],
                    "content": data['content'],
                    "date": data['date']
                })  # 添加到医生的咨询记录
                doctor.serve += 1
                doctor.save()
                user = User.objects.get(id=uid)  # 用户信息
                user.advisory.append({
                    "id": doctor.id,
                    "name": doctor.name,
                    "tel": data['tel'],
                    "content": data['content'],
                    "date": data['date']
                })  # 添加到用户的咨询记录
                user.save()
                # 记录平台数据：咨询次数
                log = PlatformLog.objects.filter(date=formatTime(date=True))
                if log:
                    log = log.first()
                    log.log['advisory'] += 1
                    log.save()
                else:
                    PlatformLog.objects.create(date=formatTime(date=True),
                                               log={"register": 0, "visit": 1, "test": 0, "advisory": 1})
                return JsonResponse({'state': True})
            except:
                return JsonResponse({'state': False})
